Add generic agent support (bring your own agent)#1639
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request adds generic agent support to Spec Kit, allowing users with unsupported AI agents to scaffold projects immediately by specifying their agent's command directory. The PR also includes undocumented support for the Antigravity (agy) agent.
Changes:
- Added
--ai generic --ai-commands-dir <path>support for bring-your-own-agent functionality - Added Antigravity (agy) as a new supported agent (undocumented in PR description)
- Updated release packaging, agent context scripts, and documentation
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/specify_cli/init.py | Added generic and agy to AGENT_CONFIG, --ai-commands-dir parameter with validation, directory renaming logic for generic agent, check command exclusion for generic |
| scripts/powershell/update-agent-context.ps1 | Added agy and generic cases to agent context update script |
| scripts/bash/update-agent-context.sh | Added agy and generic cases to agent context update script |
| pyproject.toml | Version bump to 0.1.1 |
| README.md | Updated supported agents table and CLI reference with agy, generic, and --ai-commands-dir option |
| CHANGELOG.md | Added 0.1.1 release entry documenting generic agent support |
| AGENTS.md | Added Generic to agent table |
| .gitignore | Removed trailing whitespace (cosmetic) |
| .github/workflows/scripts/create-release-packages.sh | Added agy and generic to agent list and build cases |
| .github/workflows/scripts/create-release-packages.ps1 | Added generic to agent list (missing agy support) |
| .github/workflows/scripts/create-github-release.sh | Added agy and generic template packages to release uploads |
Comments suppressed due to low confidence (2)
src/specify_cli/init.py:1114
- When users run the init command without the --ai flag, the interactive agent selection menu includes 'generic' as an option (line 1102 creates choices from all agents in AGENT_CONFIG). However, if a user selects 'generic' interactively, they will immediately hit the validation error at line 1111 because --ai-commands-dir cannot be provided through the interactive flow. Consider either excluding 'generic' from the interactive menu, or prompting for the commands directory when 'generic' is selected interactively.
else:
# Create options dict for selection (agent_key: display_name)
ai_choices = {key: config["name"] for key, config in AGENT_CONFIG.items()}
selected_ai = select_with_arrows(
ai_choices,
"Choose your AI assistant:",
"copilot"
)
# Validate --ai-commands-dir usage
if selected_ai == "generic":
if not ai_commands_dir:
console.print("[red]Error:[/red] --ai-commands-dir is required when using --ai generic")
console.print("[dim]Example: specify init my-project --ai generic --ai-commands-dir .myagent/commands/[/dim]")
raise typer.Exit(1)
src/specify_cli/init.py:1195
- The directory move operation could fail if the target directory already exists. The shutil.move() function will raise an exception if target_dir already exists as a directory. Consider adding a check to handle this case gracefully, either by removing the existing directory first, merging contents, or providing a clear error message to the user.
shutil.move(str(placeholder_dir), str(target_dir))
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
30758f2 to
3e630a4
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (3)
src/specify_cli/init.py:1327
- The ai_commands_dir parameter is not validated for malicious path traversal (e.g., "../../../etc/passwd") or absolute paths. While users are creating their own projects, allowing arbitrary paths could lead to unexpected behavior or security issues. Consider validating that the path is relative and doesn't contain path traversal sequences before using it.
# Validate --ai-commands-dir usage
if selected_ai == "generic":
if not ai_commands_dir:
console.print("[red]Error:[/red] --ai-commands-dir is required when using --ai generic")
console.print("[dim]Example: specify init my-project --ai generic --ai-commands-dir .myagent/commands/[/dim]")
raise typer.Exit(1)
elif ai_commands_dir:
console.print(f"[red]Error:[/red] --ai-commands-dir can only be used with --ai generic (not '{selected_ai}')")
raise typer.Exit(1)
src/specify_cli/init.py:1414
- When using shutil.move to rename the placeholder directory to the user-specified path, if the target_dir already exists, shutil.move will place the source inside the target rather than replacing it. This could lead to unexpected directory structure (e.g., .myagent/commands/commands/ instead of .myagent/commands/). Consider checking if target_dir exists and handling this case explicitly, or using a different approach that ensures the expected structure.
# For generic agent, rename placeholder directory to user-specified path
if selected_ai == "generic" and ai_commands_dir:
placeholder_dir = project_path / ".speckit" / "commands"
target_dir = project_path / ai_commands_dir
if placeholder_dir.is_dir():
target_dir.parent.mkdir(parents=True, exist_ok=True)
shutil.move(str(placeholder_dir), str(target_dir))
# Clean up empty .speckit dir if it's now empty
speckit_dir = project_path / ".speckit"
if speckit_dir.is_dir() and not any(speckit_dir.iterdir()):
speckit_dir.rmdir()
src/specify_cli/init.py:1414
- There is no test coverage for the generic agent directory renaming logic (lines 1404-1414) which moves .speckit/commands to the user-specified directory. This is a critical path that could fail in multiple ways (target exists, permissions issues, parent directory creation) and should have comprehensive test coverage.
# For generic agent, rename placeholder directory to user-specified path
if selected_ai == "generic" and ai_commands_dir:
placeholder_dir = project_path / ".speckit" / "commands"
target_dir = project_path / ai_commands_dir
if placeholder_dir.is_dir():
target_dir.parent.mkdir(parents=True, exist_ok=True)
shutil.move(str(placeholder_dir), str(target_dir))
# Clean up empty .speckit dir if it's now empty
speckit_dir = project_path / ".speckit"
if speckit_dir.is_dir() and not any(speckit_dir.iterdir()):
speckit_dir.rmdir()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
3e630a4 to
aac73d5
Compare
- Add --ai generic option for unsupported AI agents (bring your own agent) - Require --ai-commands-dir to specify where agent reads commands from - Generate Markdown commands with $ARGUMENTS format (compatible with most agents) - Rebuild CHANGELOG from GitHub releases (last 10 releases) - Align version to 0.1.3 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
aac73d5 to
8b9ba07
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
scripts/bash/update-agent-context.sh:38
- The comment on line 38 documenting valid agent types is missing "generic" in the agent list. This should be updated to include "generic" for consistency with the error message on line 645 and to accurately document the supported options.
Expected: # Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder|generic
# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # For generic agent, rename placeholder directory to user-specified path | ||
| if selected_ai == "generic" and ai_commands_dir: | ||
| placeholder_dir = project_path / ".speckit" / "commands" | ||
| target_dir = project_path / ai_commands_dir | ||
| if placeholder_dir.is_dir(): | ||
| target_dir.parent.mkdir(parents=True, exist_ok=True) | ||
| shutil.move(str(placeholder_dir), str(target_dir)) | ||
| # Clean up empty .speckit dir if it's now empty | ||
| speckit_dir = project_path / ".speckit" | ||
| if speckit_dir.is_dir() and not any(speckit_dir.iterdir()): | ||
| speckit_dir.rmdir() | ||
|
|
||
| ensure_executable_scripts(project_path, tracker=tracker) | ||
|
|
||
| ensure_constitution_from_template(project_path, tracker=tracker) | ||
|
|
||
| if ai_skills: | ||
| skills_ok = install_ai_skills(project_path, selected_ai, tracker=tracker) |
There was a problem hiding this comment.
The directory renaming logic for generic agent happens before install_ai_skills is called, which creates a problem. After renaming, the commands are moved from .speckit/commands to the user-specified ai_commands_dir. However, when install_ai_skills is called on line 1421, it will look for templates at project_path / "commands" (since agent_folder is None for generic at line 1058-1062). This means it won't find the commands in the user-specified directory and will fall back to the repo-relative path, which may not work correctly in all deployment scenarios. Consider either: (1) passing ai_commands_dir to install_ai_skills so it can look in the right location for generic agent, or (2) performing the directory rename after skills installation, or (3) documenting that --ai-skills is not supported with --ai generic.
Summary
Adds
--ai generic --ai-commands-dir <path>support tospecify init, enabling users with unsupported AI agents to scaffold Spec Kit projects immediately.Closes #1638
Changes
Core CLI (
src/specify_cli/__init__.py):generictoAGENT_CONFIG(folder=None,requires_cli=False)--ai-commands-dirparameter toinit()--ai generic, rejected with other agentsuser's
--ai-commands-dirpathgenericfromcheck()command (not a real tool to check)Release packaging (3 scripts):
genericto agent lists and case/switch statements.speckit/commands/as placeholder directory in ZIPsAgent context scripts (bash + PowerShell):
genericcase with informational messageDocumentation:
Usage
Testing
All 39 existing tests pass.